package ruleengine.worker;

import static org.awaitility.Awaitility.await;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;

import java.util.concurrent.TimeUnit;

import org.junit.jupiter.api.Test;

import com.ruleengine.worker.exception.ChainRunnerException;
import com.ruleengine.worker.model.Chain;
import com.ruleengine.util.model.Message;
import com.ruleengine.worker.runner.chain.DisruptorChainRunner;


/**
 * @author lianghanwei on 2024/3/3
 */
public class ChainRunnerTest extends ChainBaseTest{

    @Test
    public void processMessage() {
        Chain chain = buildChain(3);

        DisruptorChainRunner<Message> chainRunner = new DisruptorChainRunner<>(chain, null);
        chainRunner.start();

        chainRunner.process(buildMessage(0));
        chainRunner.process(buildMessage(0));
        chainRunner.process(buildMessage(0));
        chainRunner.process(buildMessage(0));
        chainRunner.process(buildMessage(0));
        chainRunner.process(buildMessage(0));

        await().atMost(1, TimeUnit.SECONDS).until(() -> isRingBufferEmpty(chainRunner));

        chainRunner.stop();
        chainRunner.close();
    }

    @Test
    public void processMessageWithoutStart() {
        Chain chain = buildChain(3);

        DisruptorChainRunner<Message> chainRunner = new DisruptorChainRunner<>(chain, null);

        chainRunner.process(buildMessage(0));

        assertFalse(isRingBufferEmpty(chainRunner));
    }

    @Test
    public void processMessageAfterStopAndClose() {
        Chain chain = buildChain(3);

        DisruptorChainRunner<Message> chainRunner = new DisruptorChainRunner<>(chain, null);
        chainRunner.start();
        chainRunner.stop();
        // chain runner statusPhase = DELETED
        chainRunner.close();

        assertThrows(ChainRunnerException.class, () -> chainRunner.process(buildMessage(0)));
    }

    private boolean isRingBufferEmpty(DisruptorChainRunner<Message> chainRunner) {
        return chainRunner.getBufferSize() <= 0;
    }
}
